package com.baseproject.util;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import com.baseproject.BaseApplication;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import static com.baseproject.appconfig.AppConfigBaseProject.APPLICATION_NAME;
import static com.baseproject.appconfig.AppConfigBaseProject.FILE_POSTFIX;

/**
 * @version V1.0  2017/4/2上午9:38
 * @author:OliverTan(www.tandunzhao.cn)
 */
public class FileUtil {
  public static final String TAG = "FileUtil";


  /**
   * 获取文件编码
   * @param fileName
   * @return
   */
  public static String getCharset(String fileName) {
    if(isFileExist(fileName)) {
      BufferedInputStream bis = null;
      String charset = "GBK";
      byte[] first3Bytes = new byte[3];
      try {
        boolean checked = false;
        bis = new BufferedInputStream(new FileInputStream(fileName));

        bis.mark(0);
        int read = bis.read(first3Bytes, 0, 3);
        if (read == -1)
          return charset;
        if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
          charset = "UTF-16LE";
          checked = true;
        } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
          charset = "UTF-16BE";
          checked = true;
        } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {
          charset = "UTF-8";
          checked = true;
        }
        bis.mark(0);
        if (!checked) {
          while ((read = bis.read()) != -1) {
            if (read >= 0xF0)
              break;
            if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的，也算是GBK
              break;
            if (0xC0 <= read && read <= 0xDF) {
              read = bis.read();
              if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF)
                // (0x80 - 0xBF),也可能在GB编码内
                continue;
              else
                break;
            } else if (0xE0 <= read && read <= 0xEF) {// 也有可能出错，但是几率较小
              read = bis.read();
              if (0x80 <= read && read <= 0xBF) {
                read = bis.read();
                if (0x80 <= read && read <= 0xBF) {
                  charset = "UTF-8";
                  break;
                } else
                  break;
              } else
                break;
            }
          }
        }
      } catch (Exception e) {
        Log.e(TAG, "getCharset: ", e);
      } finally {
        if (bis != null) {
          try {
            bis.close();
          } catch (Exception e) {
            Log.e(TAG, "getCharset: ", e);
          }
        }
      }
      return charset;
    }
    return "UTF-8";
  }

  /**
   * 读取文件
   * @param file
   * @return
   */
  public static String getStringFromFile(File file) {
    if (file == null) {
      return null;
    }
    try {
      byte[] bytes = getBytesFromFile(file);
      String charset = getCharset(file.getAbsolutePath());
      //Log.e(TAG, "getStringFromFile: charset = " + charset + "    " + file.getAbsolutePath());
      return new String(bytes, charset);
    } catch (Exception e) {
      Log.e(TAG, "getStringFromFile: ", e);
    }
    return null;
  }

  /**
   * 读取文件
   * @param file
   * @return
   */
  public static byte[] getBytesFromFile(File file) {
    if (file == null) {
      return null;
    }
    try {
      FileInputStream stream = new FileInputStream(file);
      ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
      byte[] b = new byte[1000];
      for (int n; (n = stream.read(b)) != -1; ) {
        out.write(b, 0, n);
      }
      stream.close();
      out.close();
      return out.toByteArray();
    } catch (Exception e) {
      Log.e(TAG, "getBytesFromFile: ", e);
    }
    return null;
  }

  /**
   * 写文件
   * @param file
   * @param fileContent
   */
  public static void writeFile(File file, String fileContent) {
    try {
      createFile(file);
      OutputStream outStream = new FileOutputStream(file);
      //OutputStreamWriter out = new OutputStreamWriter(outStream, "UTF-8");
      OutputStreamWriter out = new OutputStreamWriter(outStream);
      out.write(fileContent);
      out.close();
    } catch (Exception e) {
      Log.e(TAG, "writeFile: ", e);
    }
  }

  public static void writeFile(File file, byte[] fileContents) {
    try {
      createFile(file);
      OutputStream outStream = new FileOutputStream(file);
      outStream.write(fileContents);
      outStream.flush();
      outStream.close();
    } catch (Exception e) {
      Log.e(TAG, "writeFile: ", e);
    }
  }

  /**
   * 写文件
   * @param filePathAndName
   * @param fileContent
   */
  public static void writeFile(String filePathAndName, String fileContent) {
    writeFile(new File(filePathAndName), fileContent);
  }

  /**
   * 创建一个新文件
   * @param file
   */
  public static void createFile(File file) {
    try {
      String filePath = file.getAbsolutePath();
      if(file.exists()) {
        file.delete();
      }
      File fileNewFile = new File(filePath);
      fileNewFile.createNewFile();
    } catch (Exception e) {
      Log.e(TAG, "createFile: ", e);
    }
  }

    /**
     * 根据相对文件目录生成对应的完整文件目录，如果目录不存在自动创建
     * @param fileRelativePath
     * @return
     */
    public static String getFileFullPath(String fileRelativePath) {
        String[] pathSections = fileRelativePath.split("/");
        String cachePath = getCacheRootPath();
        StringBuilder sb = new StringBuilder();
        sb.append(cachePath);
        for (int i = 0; i < pathSections.length - 1; i++) {
            sb.append(File.separator).append(pathSections[i]);
        }
        createDirs(sb.toString());
        String fileName = pathSections[pathSections.length - 1];
        sb.append(File.separator).append(fileName);
        if (!fileName.contains(".")) { //如果文件名尚未制定文件类型
            sb.append(FILE_POSTFIX);
        }
        return sb.toString();
    }

  /**
   * 创建文件夹
   * @param path
   */
  public static void createDirs(String path) {
    if(!isFileExist(path)) {
      File file = new File(path);
      file.mkdirs();
    }
  }

  /**
   * 判断 文件／文件夹 是否存在
   * @param path
   * @return
   */
  public static boolean isFileExist(String path) {
    File file = new File(path);
    return file.exists();
  }


  /**
   * 获取缓存根目录
   * @param context
   * @return
   */
  public static String getCacheRootPath(Context context) {
    String cacheRootPath = null;
    if(FileUtil.isSdCardAvailable()) {
      cacheRootPath = context.getExternalCacheDir().getPath();
    } else {
      cacheRootPath = context.getCacheDir().getPath();
    }
    return cacheRootPath;
  }

  /**
   * 获取图书缓存根目录
   * @return
   */
  public static String getCacheRootPath() {
    StringBuilder sb = new StringBuilder();
    if(isSdCardAvailable()) {
      String cacheSdRootPath = getSdCardRootPath();
      sb.append(cacheSdRootPath).append(File.separator)
              .append(APPLICATION_NAME).append(File.separator);
      createDirs(sb.toString());
      return sb.toString();
    } else {
      String cacheRootPath = getCacheRootPath(BaseApplication.getApplication());
      sb.append(cacheRootPath).append(File.separator);
      createDirs(sb.toString());
      return sb.toString();
    }
  }

  /**
   * 获取SD Card 根目录
   * @return
   */
  public static String getSdCardRootPath() {
    if(isSdCardAvailable()) {
      return Environment.getExternalStorageDirectory().getPath();
    }
    return null;
  }

  /**
   * 判断SD卡可用
   * @return
   */
  public static boolean isSdCardAvailable() {
    return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
  }
}
